//
//  dlist_node.h
//  pr_fun1
//
//  Created by chenyh on 2021/1/25.
//

#ifndef dlist_node_h
#define dlist_node_h

#include <stdio.h>
#include "iterator.h"
/*双向链表
 由于结点中新增了一个指针，因此其内存开销将会是单向链表的双倍。
 在实际应用中，用该权衡效率与内存空间。
 在内存资源紧缺的场合，如何节点的添加、删除操作很少，一点效率的影响可以接受，则
 选择使用单项链表。
 而不是一味地追求效率，认为双向链表比单向链表好，始终选择使用双向链表。
 头结点p_prev和尾结点的p_next直接被设置为了NULL。
 此时，如果要直接由头结点找到尾结点，或者由尾结点找到头结点，都必须遍历
 整个链表。可以对着两个指针稍加利用，使头结点的p_prev指向尾部节点，尾节点的p_next
 指向头结点，此时，该双向链表就成了一个循环双向链表。
 为了便于区分头尾结点与普通节点，可以单独定义一个头结点类型。比如：
 由于此时还没有添加其它任何节点，仅存在一个头结点，因此该头结点既是第一个节点（头结点）
 又是最后一个节点（尾结点）。
 按照循环链表的定义，尾节点的p_next指向头结点，头结点的p_prev指向尾结点。
 因此，仅有头结点时，其p_next和p_prev都指向本身。
 head.p_next = &head;
 head.p_prev = &head;
 */
typedef struct _dlist_node{
    struct _dlist_node *p_next;
    struct _dlist_node *p_prev;
}dlist_node_t;

typedef dlist_node_t dlist_head_t;

typedef int(*dlist_node_process_t)(void *p_arg,dlist_node_t *p_node);

///类型参数为一个p_arg指针和一个结点指针,返回值为int类型的函数指针。
///每调用到一个结点均会调用pfn_node_process指向的函数

///初始化头结点
int dlist_init(dlist_head_t *p_head);
///寻找某一结点的前一结点-》指向前驱的指针
dlist_node_t *dlist_prev_get(dlist_head_t *p_head,dlist_node_t * p_pos);
///寻找某一结点的后一结点 -》指向后继的指针
dlist_node_t *dlist_next_get(dlist_head_t *p_head,dlist_node_t * p_pos);
///获取尾结点
dlist_node_t *dlist_tail_get(dlist_head_t *p_head);
///获取开始位置，第一个用户结点
dlist_node_t *dlist_begin_get(dlist_head_t * p_head);
///获取结束位置，尾结点下一个结点的位置
dlist_node_t *dlist_end_get(dlist_head_t * p_head);
///将结点添加到链表尾部
int dlist_add_tail(dlist_head_t * p_head,dlist_node_t *p_node);
///通用的函数,可以将结点添加到任意结点之后。
int dlist_add(dlist_head_t * p_head,dlist_node_t *p_pos,dlist_node_t *p_node);
///通用的函数，可以实现一个删除任意结点的函数
int dlist_del(dlist_head_t * p_head, dlist_node_t *p_node);
///遍历结点

int dlist_foreach(dlist_head_t         *p_head,
                  dlist_node_process_t pfn_node_process,
                  void                 *p_arg);

void dlist_iterator_if_get(iterator_if_t *p_if);

#endif /* dlist_node_h */
